package belf.migrate.api.table.schema;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

/** 表示一个关系数据库表的基本信息 */
public final class CatalogTable implements Serializable {

    private static final long serialVersionUID = 1L;

    /** Used to identify the table. */
    private final TableIdentifier tableId;

    /** The table schema metadata. */
    private final TableSchema tableSchema;
    /** 保存选项。当前没啥用 */
    private final Map<String, String> options;
    /** 表的注释信息 */
    private final String comment;
    /** 对应的数据库类型，参考{@link belf.migrate.api.common.DatabaseIdentifier} */
    private final String catalogName;
    /** 表是否有自增字段 */
    private final boolean autoIncreament;

    private final Map<String, ColumnMetaData> columnMap = new HashMap<>();

    public static CatalogTable of(TableIdentifier tableId, CatalogTable catalogTable) {
        return new CatalogTable(
                tableId,
                catalogTable.getTableSchema(),
                catalogTable.getOptions(),
                catalogTable.getComment(),
                catalogTable.getCatalogName());
    }

    public static CatalogTable of(
            TableIdentifier tableId,
            TableSchema tableSchema,
            Map<String, String> options,
            String comment) {
        return new CatalogTable(
                tableId, tableSchema, options, comment, tableId.getCatalogName());
    }

    public static CatalogTable of(
            TableIdentifier tableId,
            TableSchema tableSchema,
            Map<String, String> options,
            String comment,
            String catalogName) {
        return new CatalogTable(tableId, tableSchema, options, comment, catalogName);
    }

    private CatalogTable(
            TableIdentifier tableId,
            TableSchema tableSchema,
            Map<String, String> options,
            String comment) {
        this(tableId, tableSchema, options, comment, tableId.getCatalogName());
    }

    private CatalogTable(
            TableIdentifier tableId,
            TableSchema tableSchema,
            Map<String, String> options,
            String comment,
            String catalogName) {
        this.tableId = tableId;
        this.tableSchema = tableSchema;
        // Make sure the options and partitionKeys are mutable
        this.options = new HashMap<>(options);
        this.comment = comment;
        this.catalogName = catalogName;
        this.autoIncreament = tableSchema.getColumns().stream().anyMatch(new Predicate<ColumnMetaData>() {
            @Override
            public boolean test(ColumnMetaData columnMetaData) {
                return columnMetaData.isAutoIncrement();
            }
        });

        tableSchema.getColumns().forEach(columnMeta->{
            columnMap.put(columnMeta.getColumnName().toUpperCase(), columnMeta);

        });
    }

    public TableIdentifier getTableId() {
        return tableId;
    }

    public TablePath getTablePath() {
        return tableId.toTablePath();
    }

    public TableSchema getTableSchema() {
        return tableSchema;
    }

    public Map<String, String> getOptions() {
        return options;
    }

    public String getComment() {
        return comment;
    }

    public String getCatalogName() {
        return catalogName;
    }

    public boolean isAutoIncreament() {
        return autoIncreament;
    }

    public ColumnMetaData getColumn(String colomnName) {
        return columnMap.get(colomnName.toUpperCase());
    }

    public Map<String, ColumnMetaData> getColumnMap() {
        return columnMap;
    }

    @Override
    public String toString() {
        return "CatalogTable{"
                + "tableId="
                + tableId
                + ", tableSchema="
                + tableSchema
                + ", options="
                + options
                + ", comment='"
                + comment
                + '\''
                + ", catalogName='"
                + catalogName
                + '\''
                + '}';
    }
}
